/**
* @name HiveGeoPlanet Google
* @version 0.9.0
* @author Joe Johnston <joe@socialhive.org>
* @copyright (c) 2009 Joe Johnston
* http://socialhive.org/hivemaps
* http://code.google.com/p/hivemaps
*
* Creates SOCIALHIVE.geo.geocoder
*
**/

/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/

if (!window.gettext) {
  gettext = function(s){return s;};
}

(function($){  
  function queryGeoPlanet(obj, url, query, callback, countrycode, types, count, start, select, lang) {
		query = (query) ? ".q('"+encodeURIComponent(query)+"'"+(countrycode?','+countrycode:'')+')' : '';
		var typestr = '';
		if (types) {
			typestr = '.type(';
			for (var i=0; i<types.length; i++)
			  typestr += types[i]+',';
			typestr = typestr.slice(0,-1)+')';	  
    }
    url += (query && types) ? '$and('+query+','+typestr+')' : (query || typestr);
		if (count)
		  url += ';count='+count;
		url += '?format=json';
		if (start)
		  url += '&start='+start;
		if (select)
		  url += '&select='+select;
		if (lang)
		  url += '&lang='+lang;
		if (obj.jsonp)
		  url += '&callback=?';
		url += '&appid='+obj.appid;
	  $.getJSON(url, null, callback);    
  }
  
	var HiveGeoPlanet = {
	  url: 'http://where.yahooapis.com/v1/',
	  jsonp: true,
	  appid: '',
	  places: {
	    earth: {'name':gettext('Earth'), 'attrs':{'type':'Planet'}}
	  },
	  placeHierarchy: ['country', 'admin1', 'admin2', 'admin3', 'locality1', 'locality2'],
		geocodeAccuracy: ['Unknown', 'Planet', 'Continent', 'Country', 'Admin1', 'Admin2', 'Admin3', 'Town', 'Suburb', 'Post code'],
		geocodeMessages: {
			en: {
				200: 'Success',
				400: 'Server error.',
				404: 'Unable to find a matching location.',
				406: 'Invalid query.'
			}
		},
		getErrorMessage: function(result) {
			return (result.error && result.error.description) ? result.error.description : this.geocodeMessages.en[400];
		},
		createPlace: function(name, type) {
		  return {'name':name, 'attrs':{'type':type}};
		},
		getPlace: function(placeid, callback, select, lang) {
      return queryGeoPlanet(this, this.url+'place/'+placeid, null, callback, null, null, null, null, select, lang);
		},
		getPlaces: function(place, callback, countrycode, types, count, start, select, lang) {
      return queryGeoPlanet(this, this.url+'places', place, callback, countrycode, types, count, start, select, lang);
		},
		getBelongTos: function(placeid, callback, query, countrycode, types, count, start, select, lang) {
      return queryGeoPlanet(this, this.url+'place/'+placeid+'/belongtos', query, callback, countrycode, types, count, start, select, lang);
		},
		getChildren: function(placeid, callback, query, countrycode, types, count, start, select, lang) {
      return queryGeoPlanet(this, this.url+'place/'+placeid+'/children', query, callback, countrycode, types, count, start, select, lang);
		},
		getParent: function(placeid, callback, select, lang) {
      return queryGeoPlanet(this, this.url+'place/'+placeid+'/parent', null, callback, null, null, null, null, select, lang);
		},
		filterByArea: function(places, minbounds, maxbounds) {
		  console.log(arguments);
	    var a = [];
	    var min = (minbounds) ? SOCIALHIVE.geo.utils.distance(minbounds.southWest.latitude, minbounds.southWest.longitude, 
	        minbounds.northEast.latitude, minbounds.northEast.longitude) : 0;
	    var max = (maxbounds) ? SOCIALHIVE.geo.utils.distance(maxbounds.southWest.latitude, maxbounds.southWest.longitude, 
	        maxbounds.northEast.latitude, maxbounds.northEast.longitude) : 999999999;
	    for (var i=places.length; i--;) {
	      var place = places[i];
	      var dist = SOCIALHIVE.geo.utils.distance(place.boundingBox.southWest.latitude, place.boundingBox.southWest.longitude,
	          place.boundingBox.northEast.latitude, place.boundingBox.northEast.longitude);
	      if (min <= dist && dist <= max) {
	        place.dist = dist;
	        a.push(place);
	      }
	    }
		  return a;
		},
		/**
		* Find the closest point in getPlaces results to lat,lon.
		**/
		getNearestResult: function(results, lat, lon) {
			var nearest = {distance: 999999999, result: null};
			var places = results.places.place;
			for (var i=places.length; i--;) {
				var d = SOCIALHIVE.geo.utils.distance(places[i].centroid.latitude, places[i].centroid.longitude, lat, lon);
				if (d < nearest.distance) {
					nearest.distance = d;
					nearest.result = places[i];
				}
			}
			return nearest;
		},
    buildGeoHierarchy: function(place) {
      var chain = [this.places.earth, {'name':SOCIALHIVE.geo.utils.getContinentFromCountry(place['country attrs'].code, place.lang), 'attrs':{'type':'Continent'}}];      
      var len = this.placeHierarchy.length;
      for (var i=0; i<len; i++)
        if (place[this.placeHierarchy[i]])
          chain.push({'name':place[this.placeHierarchy[i]], 'attrs':place[this.placeHierarchy[i]+' attrs']});
      return chain;
    },
    getPlaceFullName: function(place, skip, format) {
      if (!skip)
        skip = {'Planet':1, 'Continent':1, 'County':1};
      if (!format)
        format = {'Suburb':"?,", 'Town':'?,', 'State':'? '};
      var chain = this.buildGeoHierarchy(place);
      var name = '';
      for (var i=chain.length; i--;) {
        if (chain[i].attrs.type in skip)
          continue;
        name += ' '+(chain[i].attrs.type in format ? format[chain[i].attrs.type].replace('?', chain[i].name) : chain[i].name);
      }
      return name;
    },
    getPlaceRegionCode: function(place, notrim) {
      if (!place.admin1)
        return '';
      if (notrim)
        return place['admin1 attrs'].code;
      var str = place['admin1 attrs'].code;
      var idx = str.indexOf(place['country attrs'].code);
      if (idx>=0)
        str = place['admin1 attrs'].code.substr(place['country attrs'].code.length);
      return (str[0]=='-') ? str.substr(1) : str;
    }
	};
  
  // init
  jQuery(function($) {
  });

  if (!window.SOCIALHIVE)
    window.SOCIALHIVE = {};
  if (!window.SOCIALHIVE.geo)
    window.SOCIALHIVE.geo = {};
  window.SOCIALHIVE.geo.geoplanet = HiveGeoPlanet;
})(jQuery);
